home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
blit.zip
/
BLIT.ASM
next >
Wrap
Assembly Source File
|
1988-02-21
|
24KB
|
1,071 lines
_DATA segment word public 'DATA'
include blit.def
count_begin macro
thisone = $
dw ?
endm
count_end macro a
ifdif <a>,<>
org $-a
endif
thatone = $
org thisone
dw thatone-thisone-2
org thatone
endm
;note that the two words previous to the given verb must be the offsets
; (in the data segment!) of two routines. The first (cs:put_byte_subr-4) is
; a routine that puts the byte in al with a mask of 0ffh. The second
; (cs:put_byte_subr-2) is a routine that puts the byte in al using the mask
; in dl.
put_byte_subr dw ? ;our transfer mode.
count dw ?
smaller_delta dw ?
larger_delta dw ?
epsilon dw ?
new_x_size dw ?
old_x_size dw ?
smaller_line dw ?
larger_line dw ?
compression db ?
not_compression db ?
bit_count dw ? ;count of bits in source bitmap.
line_count dw ? ;count of lines in source bitmap.
scan_line_count dw ? ;count of lines so far done.
;we precompute several things:
src_align dw ? ;source bit alignment, 0..7
src_seg dw ? ;segment of source bitmap
src_bytes dw ? ;width of source bitmap in bytes
src_left_bit db ? ;leftmost bit in source bitmap
dest_align dw ? ;destination bit alignment, 0..7
dest_bytes dw ? ;width of dest bitmap in bytes
dest_left_bit db ? ;leftmost bit in dest bitmap
;this following table is used to provide shifts of differing counts.
; On a V20, and 80x86; x=1,2,3 we could use the shift with immediate count
; instruction, but then we're screwed on 808x processors.
get_byte_ptr dw ?
get_ptrs label word
dw 0 ;shift count of zero - not used.
dw shifted_1_get ;special case - shift count of 1.
dw shifted_get
dw shifted_get
dw shifted_get
dw shifted_get
dw shifted_get
dw shifted_7_get ;special case = shift count of -1 mod 8.
shifted_get label byte
count_begin
mov ax,[si] ;get the next two bytes.
inc si
rol ax,cl ;align to screen byte.
count_end
shifted_1_get label byte
count_begin
mov ax,[si] ;get the next two bytes.
inc si
rol ax,1 ;align to screen byte.
count_end
shifted_7_get label byte
count_begin
mov ax,[si] ;get the next two bytes.
inc si
xchg ah,al ;rol ax,7 == xchg ah,al;ror ax,1
ror ax,1 ;align to screen byte.
count_end
pset_verb_1 label byte
count_begin
stosb
count_end
pset_verb_2 label byte
count_begin
xor al,es:[di]
and al,dl
xor es:[di],al
inc di ;go to the next byte.
count_end
and_not_verb_1 label byte
count_begin
not al
and es:[di],al
inc di ;go to the next byte.
count_end
and_not_verb_2 label byte
count_begin
not al
not dl
or al,dl
and es:[di],al
inc di ;go to the next byte.
count_end
preset_verb_1 label byte
count_begin
not al
stosb
count_end
preset_verb_2 label byte
count_begin
not al
xor al,es:[di]
and al,dl
xor es:[di],al
inc di ;go to the next byte.
count_end
and_verb_1 label byte
count_begin
and es:[di],al
inc di ;go to the next byte.
count_end
and_verb_2 label byte
count_begin
not dl
or al,dl
and es:[di],al
inc di ;go to the next byte.
count_end
or_verb_1 label byte
count_begin
or es:[di],al
inc di ;go to the next byte.
count_end
or_verb_2 label byte
count_begin
and al,dl ;only set the bits given in al.
or es:[di],al
inc di ;go to the next byte.
count_end
or_not_verb_1 label byte
count_begin
not al
or es:[di],al
inc di ;go to the next byte.
count_end
or_not_verb_2 label byte
count_begin
not al
and al,dl ;only set the bits given in al.
or es:[di],al
inc di ;go to the next byte.
count_end
xor_verb_1 label byte
count_begin
xor es:[di],al
inc di ;go to the next byte.
count_end
xor_verb_2 label byte
count_begin
and al,dl ;only xor the bits given in al.
xor es:[di],al
inc di ;go to the next byte.
count_end
_DATA ends
_TEXT segment byte public 'CODE'
assume cs:_TEXT, ds:_DATA, ss:_DATA
put_sized:
mov compression,1 ;assume we're compressing zeroes.
mov not_compression,0
cmp put_byte_subr,offset _pset_verb
jne put_sized_1
mov compression,-1 ;we're compressing ones
mov not_compression,1
put_sized_1:
mov ax,bit_count
mov old_x_size,ax ;remember the old h size.
mov cx,src_align ;compute the src left bit.
mov al,80h
shr al,cl
mov src_left_bit,al
mov ax,[di].right ;compute the new h size.
sub ax,[di].left
mov new_x_size,ax ;remember the new h size.
mov dest_align,bp ;compute the dest left bit.
mov cx,bp
mov al,80h
shr al,cl
mov dest_left_bit,al
mov ax,[di].bot ;compute the new v size.
sub ax,[di].top
cmp ax,line_count ;which is larger?
jb put_shrink_1 ;go if we're shrinking
;expand it here. We have more lines in the dest than the source.
mov bx,line_count ;don't include the last scan line.
mov smaller_delta,bx
mov larger_delta,ax
mov line_count,ax
mov epsilon,0
call blit_setup
mov src_seg,ax
mov bx,src_bytes
mov scan_line_count,bx
put_expand_2:
push si
push di
call put_sized_line
pop di
pop si
mov bx,epsilon
mov dx,larger_delta
add bx,smaller_delta
cmp bx,dx ;past the larger yet?
jl put_expand_3 ;no.
sub bx,dx ;yes - subtract it.
add si,src_bytes ;advance to next line.
put_expand_3:
mov epsilon,bx
add di,dest_bytes
dec line_count
jne put_expand_2
ret
put_shrink_1:
;shrink it here. We have more lines in the source than in the dest.
mov smaller_delta,ax
mov ax,line_count
mov larger_delta,ax
mov epsilon,0
call blit_setup
mov src_seg,ax
mov scan_line_count,0
put_shrink_2:
mov bx,src_bytes
add scan_line_count,bx ;include another scan line in the processing.
mov bx,epsilon
mov dx,larger_delta
add bx,smaller_delta
mov epsilon,bx
cmp bx,dx ;past the larger yet?
jl put_shrink_3 ;no.
sub bx,dx ;yes - subtract it off.
mov epsilon,bx
push si
push di
call put_sized_line
pop di
pop si
add si,scan_line_count ;move the source down a line.
mov scan_line_count,0
add di,dest_bytes ;move to the next line.
put_shrink_3:
dec line_count
jne put_shrink_2
ret
put_sized_line:
;ds:si->array, es:di->screen, bp=destination alignment,
; scan_line_count=number of scan lines to process.
;don't destroy bp.
mov ax,new_x_size ;are we changing the x size?
cmp ax,old_x_size
jb put_smaller_line ;yes - it's shorter.
ja put_larger_line ;yes - it's longer.
mov bx,ax
mov bp,dest_align ;get the destination alignment.
jmp put_scan_line ;no - same size.
put_larger_line:
mov larger_line,ax ;new is larger.
mov bit_count,ax
xor bx,bx
mov ax,old_x_size
mov smaller_line,ax
mov dl,dest_left_bit
mov dh,src_left_bit ;dh=source mask.
mov cx,bit_count
push ds
mov ds,src_seg
assume ds:nothing
mov ah,[si] ;get the first source byte.
inc si
put_larger_line_1:
xor al,al
test dh,ah ;is the source bit set?
je put_larger_line_2 ;no.
mov al,dl ;yes - get the dest bit in question.
put_larger_line_2:
call put_byte_subr ;put this byte.
add bx,smaller_line
cmp bx,larger_line
jb put_larger_line_3
sub bx,larger_line
ror dh,1 ;move over a source bit.
jnc put_larger_line_3
mov ah,[si]
inc si
put_larger_line_3:
ror dl,1 ;move over a dest bit.
adc di,0 ;if cy, move over in di.
loop put_larger_line_1 ;no.
cmp dh,80h ;did we use any of the source bits?
jne put_larger_line_5
dec si ;no - backup.
put_larger_line_5:
pop ds
assume ds:_DATA
ret
put_smaller_line:
mov smaller_line,ax
mov ax,old_x_size
mov larger_line,ax
mov bit_count,ax
xor bx,bx
mov cx,bit_count
mov dl,dest_left_bit
mov dh,src_left_bit ;dh=source mask.
push ds
mov ds,src_seg
assume ds:nothing
mov ah,7fh ;init the sampling sum.
put_smaller_line_1:
push bx
mov bx,0
put_smaller_line_6:
add ah,not_compression
test [si+bx],dh ;is the source bit set?
je put_smaller_line_2 ;no.
add ah,compression ;yes - count this bit.
put_smaller_line_2:
add bx,src_bytes ;move down a scan line.
cmp bx,scan_line_count ;have we